#include "FSMachine.h"
#include "Tracer.h"

namespace libemb{
FSMachine::FSMachine()
{
}

FSMachine::~FSMachine()
{
    quit();
}

bool FSMachine::startup(int stateID)
{
    m_currState = stateID;
    return m_thread.start(*this);
}

void FSMachine::quit()
{
    m_stateHandlerMap.clear();
    m_stateListenerSet.clear();
    m_thread.stop(-1);
}

void FSMachine::registerListener(FSListener& listener)
{
    m_stateListenerSet.insert({&listener});
}

bool FSMachine::registerState(int stateID, FSHandler& stateHandler)
{
    if (stateID<0)
    {
        TRACE_ERR_CLASS("state cannot be negative,stateID(%d)!",stateID);
        return false;
    }
    auto iter = m_stateHandlerMap.find(stateID); 
	if (iter!=m_stateHandlerMap.end())
	{
		return false;
	}
    m_stateHandlerMap.insert({stateID, &stateHandler});
    return true;
}

int FSMachine::currentState()
{
    return m_currState;
}

bool FSMachine::changeState(int stateID)
{
    if (stateID<0)
    {
        return false;
    }
    AutoLock lock(m_stateMutex);
    m_currState = stateID;
    return true;
}

void FSMachine::run(Thread& thread)
{
    int nextState = m_currState;
    while(thread.isRunning())
    {
        if (!m_stateHandlerMap.empty())
        {
            auto iter = m_stateHandlerMap.find(m_currState);
            if (iter!=m_stateHandlerMap.end())
            {
                nextState = iter->second->handleState();
                {
                    AutoLock lock(m_stateMutex);
                    m_currState = nextState;
                }
                for(auto& listener: m_stateListenerSet)
                {
                    listener->onStateChanged(m_currState);
                }
                continue;
            }
        }
        Thread::msleep(100);
    }
}
}
